package com.file.parser;


import com.file.bo.ResponseData;
import com.file.bo.mail.SCRCU;
import com.file.bo.mail.SCRCUTran;
import com.file.constant.ErrorCode;
import com.file.util.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import technology.tabula.*;
import technology.tabula.detectors.NurminenDetectionAlgorithm;
import technology.tabula.extractors.SpreadsheetExtractionAlgorithm;

import java.io.File;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 丰巢-四川农信的pdf解析类
 * @author v_wbstlu
 * @date 2023-10-30
 */
@Slf4j
public class SCRCUPdfParser extends BasePdfParser{

	public ResponseData<String> parseSCRCUPdfToJson(String daId, String filePath) {
		log.info("parseSCRCUPdfToJson started, daId:{}", daId);
    	String json = null;

    	try {
			SCRCU scrcu = parseSCRCUPdf(filePath);
			json = JsonUtils.convertObjectToJson(scrcu);
		} catch (Exception e) {
			log.error("OnError|{}||{}|{}|{}|{}", ErrorCode.FILE_PARSE_EXCEPTION.getCode(), daId, "", "", "parseSCRCUPdfToJson failed", e);
			return new ResponseData<String>(json, ErrorCode.FILE_PARSE_EXCEPTION.getCode(), ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
		}

    	log.info("parseSCRCUPdfToJson completed, daId:{}", daId);
    	return new ResponseData<String>(json, ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg());
	}

	public SCRCU parseSCRCUPdf(String filePath) {
		List<SCRCUTran> scrcuTrans = parseTrans(filePath);

		SCRCU scrcu = parseSCRCUHeader(filePath);

		scrcu.setScrcuTrans(scrcuTrans);

		return scrcu;
	}

	public SCRCU parseSCRCUHeader(String filePath) {
		SCRCU scrcu = new SCRCU();
		String pdfHeaderText = parsePdfHeaderText(filePath);
		pdfHeaderText = pdfHeaderText.substring(pdfHeaderText.indexOf("四川省农村信用社账户交易明细") + 14, pdfHeaderText.indexOf("交易日期"));

		String accountNo = pdfHeaderText.substring(pdfHeaderText.indexOf("账号：") + 3, pdfHeaderText.indexOf("户名：")).replaceAll(" ", "");//NOSONAR
		String accountName = pdfHeaderText.substring(pdfHeaderText.indexOf("户名：") + 3,pdfHeaderText.indexOf("开户行：")).replaceAll(" ", "");//NOSONAR
		String accountBank = pdfHeaderText.substring(pdfHeaderText.indexOf("开户行：") + 4,pdfHeaderText.indexOf("起止日期：")).replaceAll(" ", "");//NOSONAR
		String transDetailPeriod = pdfHeaderText.substring(pdfHeaderText.indexOf("起止日期：") + 5,pdfHeaderText.indexOf("收入合计：")).replaceAll(" ", "");//NOSONAR
		String totalIncome = pdfHeaderText.substring(pdfHeaderText.indexOf("收入合计：") + 5,pdfHeaderText.indexOf("支出合计：")).trim();
		String totalExpenditure = pdfHeaderText.substring(pdfHeaderText.indexOf("支出合计：") + 5,pdfHeaderText.indexOf("注：")).trim();
		String comment = pdfHeaderText.substring(pdfHeaderText.indexOf("注：") + 2).trim();
		scrcu.setAccountNo(accountNo);
		scrcu.setAccountName(accountName);
		scrcu.setAccountBank(accountBank);
		scrcu.setTransDetailPeriod(transDetailPeriod);
		scrcu.setTotalIncome(totalIncome);
		scrcu.setTotalExpenditure(totalExpenditure);
		scrcu.setComment(comment);
		return scrcu;
	}

	public List<SCRCUTran> parseTrans(String filePath) {
		List<SCRCUTran> scrcuTrans = new ArrayList<>();

		// 1. 读取文件
		File pdf = new File(filePath);
		
		// 2. pdfbox读取PDDocument
		try (PDDocument pdfDocument = PDDocument.load(pdf)) {

			// 3. tabula新建ObjectExtractor和NurminenDetectionAlgorithm，同时准备接收表格Rectangle的结构
			ObjectExtractor objectExtractor = new ObjectExtractor(pdfDocument);
			NurminenDetectionAlgorithm detectionAlgorithm = new NurminenDetectionAlgorithm();
			Map<Integer, List<Rectangle>> detectedTables = new HashMap<>();

			// 4. 获取每页的PageIterator
			PageIterator pages = objectExtractor.extract();

			// 5. 解析每页的Rectangle(table的位置)
			while (pages.hasNext()) {
				Page page = pages.next();
				List<Rectangle> tablesOnPage = detectionAlgorithm.detect(page);
				if (tablesOnPage.size() > 0) {
					detectedTables.put(Integer.valueOf(page.getPageNumber()), tablesOnPage);
				}
			}

			// 6.通过table位置获取表格具体内容
			SpreadsheetExtractionAlgorithm bea = new SpreadsheetExtractionAlgorithm();

			String datePattern ="^[0-9]{4}(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])$";
			Pattern regexPattern = Pattern.compile(datePattern);

			// 如果单页pdf中有多个表格，则解析出来的List<Rectangle>会有多个对象
			for (Map.Entry<Integer, List<Rectangle>> entry : detectedTables.entrySet()) {
				Page page = objectExtractor.extract(entry.getKey());

				// 四川农信默认每页只有一个表格，因此获取第0个rectangle
				Rectangle rectangle = entry.getValue().get(0);
				Page area = page.getArea(rectangle.getTop(), rectangle.getLeft(),rectangle.getBottom(),rectangle.getRight());

				List<Table> table = bea.extract(area);

				// 四川农信默认每页只有一个表格，因此获取第0个table
				Table t = table.get(0);

				for (int i = 0; i < t.getRowCount(); i++) {

					// 校验第一个字段是否是日期
					String firstField = t.getCell(i,0).getText(false);
					if (StringUtils.isBlank(firstField) && Objects.nonNull(t.getCell(i,1))) {
						firstField = t.getCell(i,1).getText(false);
					}
					Matcher matcher = regexPattern.matcher(firstField);
					if (Boolean.FALSE.equals(matcher.find())) {
						continue;
					}
					SCRCUTran scrcuTran = getTransactionByTable(t, i);
					if (StringUtils.isNotBlank(scrcuTran.getTransactionDate())) {
						scrcuTrans.add(scrcuTran);
					}
				}

			}
		}  catch (Exception e) {
			throw new RuntimeException(e);
		}
		
		return scrcuTrans;
	}

	private SCRCUTran getTransactionByTable(Table t, int i) {
		SCRCUTran scrcuTran = new SCRCUTran();
		if (StringUtils.isBlank(t.getCell(i,0).getText(false))) {
			scrcuTran.setTransactionDate(t.getCell(i,1).getText(false));
			scrcuTran.setTime(t.getCell(i,2).getText(false));
			scrcuTran.setCurrency(t.getCell(i,3).getText(false));
			scrcuTran.setTransactionAmount(t.getCell(i,4).getText(false));
			scrcuTran.setBalance(t.getCell(i,5).getText(false));
			scrcuTran.setCounterPartyAccountName(t.getCell(i,6).getText(false));
			scrcuTran.setCounterPartyAccountNo(t.getCell(i,7).getText(false));
			scrcuTran.setCounterPartyBank(t.getCell(i,8).getText(false));
			scrcuTran.setPurpose(t.getCell(i,9).getText(false));
			scrcuTran.setComment(t.getCell(i,10).getText(false));
			scrcuTran.setDate(t.getCell(i,11).getText(false));
		} else {
			scrcuTran.setTransactionDate(t.getCell(i,0).getText(false));
			scrcuTran.setTime(t.getCell(i,1).getText(false));
			scrcuTran.setCurrency(t.getCell(i,2).getText(false));
			scrcuTran.setTransactionAmount(t.getCell(i,3).getText(false));
			scrcuTran.setBalance(t.getCell(i,4).getText(false));
			scrcuTran.setCounterPartyAccountName(t.getCell(i,5).getText(false));
			scrcuTran.setCounterPartyAccountNo(t.getCell(i,6).getText(false));
			scrcuTran.setCounterPartyBank(t.getCell(i,7).getText(false));
			scrcuTran.setPurpose(t.getCell(i,8).getText(false));
			scrcuTran.setComment(t.getCell(i,9).getText(false));
			scrcuTran.setDate(t.getCell(i,10).getText(false));
		}

		return scrcuTran;
	}

	public static void main(String[] args) {
		SCRCUPdfParser pdfParser = new SCRCUPdfParser();

		SCRCU scrcu = pdfParser.parseSCRCUPdf("D:\\data\\file\\beehive-scrcu\\20231023142059.pdf");
		System.out.println(JsonUtils.convertObjectToJson(scrcu));

	}

}
